/*-----------------------------------------------------------------------*/
/* Low level disk I/O module SKELETON for FatFs     (C)ChaN, 2019        */
/*-----------------------------------------------------------------------*/
/* If a working storage control module is available, it should be        */
/* attached to the FatFs via a glue function rather than modifying it.   */
/* This is an example of glue functions to attach various exsisting      */
/* storage control modules to the FatFs module with a defined API.       */
/*-----------------------------------------------------------------------*/
#include <stdio.h>
#include "ff.h"			/* Obtains integer types */
#include "diskio.h"		/* Declarations of disk functions */
#include "../bsp_w25q64.h"
#include <stdint.h>
#include "../sdcard.h"

/* Definitions of physical drive number for each drive */
#define DEV_RAM		0	/* Example: Map Ramdisk to physical drive 0 */
#define DEV_MMC		1	/* Example: Map MMC/SD card to physical drive 1 */
#define DEV_USB		2	/* Example: Map USB MSD to physical drive 2 */

#define DEV_SPIFLASH	0
#define SECTOR_SIZE		4096
#define DEV_SDCARD	 	    1

/*-----------------------------------------------------------------------*/
/* Get Drive Status                                                      */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
	BYTE pdrv		/* Physical drive nmuber to identify the drive */
)
{
	if (pdrv == DEV_SPIFLASH) {
		// 如果ID读取成功，则设备就绪
		uint16_t id = W25Q64_readID();
		if (id == 0xEF16) {
			return RES_OK;
		}
	} else if (pdrv == DEV_SDCARD) {
        return RES_OK;
    }

	return RES_NOTRDY;
}



/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
	BYTE pdrv				/* Physical drive nmuber to identify the drive */
)
{
	if (pdrv == DEV_SPIFLASH) {
		w25q64_init_config();
	} else if (pdrv == DEV_SDCARD) {
        uint8_t res=sd_io_init();	//SD卡初始化 
        if(res == SD_OK) {
			return RES_OK;
        }
    }
	
	return RES_OK;
}



/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
	BYTE pdrv,		/* Physical drive nmuber to identify the drive */
	BYTE *buff,		/* Data buffer to store read data */
	LBA_t sector,	/* Start sector in LBA */
	UINT count		/* Number of sectors to read */
)
{
	if (pdrv == DEV_SPIFLASH) {
		uint32_t addr = sector * SECTOR_SIZE;

		for (int i = 0; i < count; i++) {
			W25Q64_read_sector(buff, addr, SECTOR_SIZE);
			addr += SECTOR_SIZE;
            buff += SECTOR_SIZE;
		}
		return RES_OK;
	} else if (pdrv == DEV_SDCARD) {
        //printf("sd_block_read sector: %d  count: %d \r\n",sector,count);
				
        uint8_t res;
        if (count == 1) {
            res = sd_block_read((uint32_t *)buff, sector * 512, 512);
        } else {
            res = sd_multiblocks_read((uint32_t*)buff,sector * 512, 512, count);	 
        }
        
        if(res == SD_OK) {
            return RES_OK;
        }
    }
	return RES_PARERR;
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/

#if FF_FS_READONLY == 0

DRESULT disk_write (
	BYTE pdrv,			/* Physical drive nmuber to identify the drive */
	const BYTE *buff,	/* Data to be written */
	LBA_t sector,		/* Start sector in LBA */
	UINT count			/* Number of sectors to write */
)
{
	if (pdrv == DEV_SPIFLASH) {
		uint32_t addr = sector * SECTOR_SIZE;

		for (int i = 0; i < count; i++) {
            W25Q64_erase_sector(addr);
			W25Q64_write_sector((uint8_t*)buff, addr, SECTOR_SIZE);
			addr += SECTOR_SIZE;
            buff += SECTOR_SIZE;
		}
		return RES_OK;
	} else if (pdrv == DEV_SDCARD) {
        //printf("sd_block_write sector: %d  count: %d \r\n",sector,count);
				
        uint8_t res;
        if (count == 1) {
            res = sd_block_write((uint32_t *)buff, sector * 512, 512);
        } else {
            res = sd_multiblocks_write((uint32_t*)buff,sector * 512, 512, count);	 
        }
        
        if(res == SD_OK) {
            return RES_OK;
        }
    }
	return RES_PARERR;
}

#endif


/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

DRESULT disk_ioctl (
	BYTE pdrv,		/* Physical drive nmuber (0..) */
	BYTE cmd,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
	if (pdrv == DEV_SPIFLASH) {
		switch (cmd)  {
			case CTRL_SYNC:			// 同步回写
				return RES_OK; 
			case GET_SECTOR_COUNT: {
				// 扇区数量
				*(DWORD * )buff = 2048;//W25Q64 有2048个大小为4k bytes 的扇区
				return RES_OK;
			}
			case GET_SECTOR_SIZE: {
				// 扇区大小
				*(WORD * )buff = 4096;//spi flash的扇区大小是 4K Bytes
				return RES_OK; 
			}
		 }
	} else if (pdrv == DEV_SDCARD) {
		switch (cmd)  {
			case CTRL_SYNC:			// 同步回写
				return RES_OK; 
			case GET_SECTOR_COUNT: {
				// 扇区数量
				*(DWORD * )buff = 1024*1024*1024 / 512;
				return RES_OK;
			}
			case GET_SECTOR_SIZE: {
				// 扇区大小
				*(WORD * )buff = 512;
				return RES_OK; 
			}
		 }
        
    }

	return RES_PARERR;
}

#include <time.h>
DWORD get_fattime(void)
{
	return (DWORD)(2022 - 80) << 25 |
		(DWORD)(3 + 1) << 21 |
		(DWORD)1 << 16 |
		(DWORD)0 << 11 |
		(DWORD)0 << 5 |
		(DWORD)0 >> 1;
}

